﻿unit UnitMain;

interface

uses
  Winapi.Windows, TlHelp32, psapi, Winapi.ShellAPI, Winapi.Messages, Registry,
  System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls,
  Vcl.Forms, Vcl.Dialogs, Vcl.Imaging.pngimage, Vcl.ExtCtrls, Vcl.StdCtrls,
  Vcl.Menus,UnitAbout,IniFiles, dxGDIPlusClasses;

const
  mousemsg = wm_user + 1;
  iid = 100;
   //文件图标绘制位置
  FileIconLeft = 0;
  FileIconTop = 6;
 //窗体图标绘制位置
  WinIconLeft = 20;
  WinIconTop = 6;
  RedrawRect: TRect = (
    Left: 0;
    Top: 0;
    Right: 40;
    Bottom: 40
  );
  PROCESS_NAME_Win32 = $00000000;
  PROCESS_NAME_NATIVE = $00000001; //返回DOS格式

type
  TQueryFullProcessImageName = function(hProcess: THandle; dwFlags: DWORD; lpExeName: LPSTR; lpdwSize: PDWORD): BOOL; stdcall;

type
 //----自定义图标句柄结构----
  IWindowHandle = record
    WindowHanlde: LongWord;
    WindowText: string;       // 窗体标题
    WindowClass: string;       // 窗体类名
    WindowRect: TRect;          // 窗体尺寸

    WinThreadID: LongWord;       // 线程ID
    WinProcessId: LongWord;       // 进程ID
    FullFileName: string;       // 完整路径
    ExeFileIcon: LongWord;       // 文件图标
    WindowIcon: Longword;  //窗体标题栏图标句柄
  end;
   {-- 枚举中 返回 模块信息结构 --}

  TMODULEENTRY32 = record
    dwSize: DWORD;        // 本结构尺寸
    th32ModuleID: DWORD;  // This module
    th32ProcessID: DWORD; // owning process
    GlblcntUsage: DWORD;  // Global usage count on the module
    ProccntUsage: DWORD;  // Module usage count in th32ProcessID's context
    modBaseAddr: PBYTE;   // Base address of module in th32ProcessID's context
    modBaseSize: DWORD;   // Size in bytes of module starting at modBaseAddr
    hModule: HMODULE;     // The hModule of this module in th32ProcessID's context
    szModule: array[0..255] of Char;
    szExePath: array[0..260 - 1] of Char; // 模块完整路径
  end;

type
  TFrmmain = class(TForm)
    Img_BG: TImage;
    PM_Main: TPopupMenu;
    E1: TMenuItem;
    TimerMove: TTimer;
    lbl_exit: TLabel;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    Labelexit: TLabel;
    PopupMenu1: TPopupMenu;
    N4: TMenuItem;
    N11: TMenuItem;
    N9: TMenuItem;
    Timer1: TTimer;
    Image1: TImage;
    Image2: TImage;
    Image3: TImage;
    Image4: TImage;
    Image5: TImage;
    Image6: TImage;
    Image7: TImage;
    Image8: TImage;
    Timer2: TTimer;
    ImageAbout: TImage;
    procedure Img_BGMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure E1Click(Sender: TObject);
    procedure TimerMoveTimer(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure Image2MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure Image2MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure Image2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure Img_YTGClick(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure lbl_exitClick(Sender: TObject);
    procedure LabelexitClick(Sender: TObject);
    procedure N9Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Label1Click(Sender: TObject);
    procedure Image1Click(Sender: TObject);
    procedure Timer2Timer(Sender: TObject);
    procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure ImageAboutDblClick(Sender: TObject);
    procedure ImageAboutMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Label1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormDestroy(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
    procedure WMWINDOWPOSCHANGING(var Msg: TWMWINDOWPOSCHANGING); message WM_WINDOWPOSCHANGING;
  public
    { Public declarations }
    isshow: boolean; //移动控件
    procedure mousemessage(var message: tmessage); message mousemsg;
    procedure zdyx(a, b: string; c: boolean);
  end;

var
  Frmmain: TFrmmain;
  Hash: THashedStringList;
  FWidth, FHeight: Integer; //窗體原始大小
  YTGWidth, YTGHeight: integer; //中間按鈕大小
  FLeft, FTop: Integer; //記錄上一次 Form所在位置
  g_lib: THandle = 0;
  g_bIsWindowsVISTAorLater: Boolean;
  bMoving: Boolean; //正在移動。
  bHided: Boolean;  //是否已隱藏
  Docked: Boolean;  //是否正停靠
  DockedDirection: string; // Top Bottom Left Right
  bEnterOrLeave: Boolean; //進入還是離開
  MinShowLength: Integer = 3; //隱藏後顯示的部分。
  WorkAreaHight, WorkAreaWidth: integer; //屏幕高寬
  cOffset: Integer; //移動速度。MoveSpeed.

  iTempX, iTempY: integer; //控件位置。
  bStartMove: boolean; //移动控件
  IWindow_Handle: array of IWindowHandle;
  hndRunOnce: HWND;
  ntida: TNotifyIcondataA;
  WindowText: string;       // 窗体标题
  WindowClass: string;       // 窗体类名
  WindowIcon: LongWord;       // 窗体图标
  WindowRect: TRect;          // 窗体尺寸

  WinThreadID: LongWord;       // 线程ID
  WinProcessId: LongWord;       // 进程ID

  ModuleStruct: TMODULEENTRY32; // 模块信息结构
  ModuleHandle: LongWord;       // 快照句柄
  FoundModule: Boolean;       // 是否找到模块

  FullFileName: string;       // 完整路径
  FileIconIndex: UINT = 0;       // 图标索引
  ExeFileIcon: LongWord;       // 文件图标
  QueryFullProcessImageName: TQueryFullProcessImageName;
   //--------------API  Function------------------

function CreateToolhelp32Snapshot(dwFlags, th32ProcessID: DWORD): THandle; stdcall; external 'kernel32.dll' name 'CreateToolhelp32Snapshot';

function Module32First(hSnapshot: THandle; var lpme: TModuleEntry32): BOOL; stdcall; external 'kernel32.dll' name 'Module32First';

function Module32Next(hSnapshot: THandle; var lpme: TModuleEntry32): BOOL; stdcall; external 'kernel32.dll' name 'Module32Next';
   //--------------API  Function------------------

procedure SwitchToThisWindow(hWnd: Thandle; fAltTab: boolean); stdcall; external 'User32.dll';
procedure MyEnumWindows();
function EnumWindowsProc(WinHwnd: HWND; lParam: LPARAM): Boolean; stdcall;
function GetProcessImageFileName(hProcess: Cardinal; lpImageFileName: LPSTR; nSize: DWORD): DWORD; stdcall;  external 'PSAPI.dll' name 'GetProcessImageFileNameA';
implementation

{$R *.dfm}

uses UnitAboutN;
     //----尾串匹配否,不区分大小写----
function AnsiEndsText(const ASubText, AText: string): Boolean;
var
  P: PChar;
  L, L2: Integer;
begin
  P := PChar(AText);
  L := Length(ASubText);
  L2 := Length(AText);
  Inc(P, L2 - L);
  if L > L2 then
    Result := FALSE
  else
    Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, P, L, PChar(ASubText), L) = 2;
end;

   //----转为10进制形式字符串----
function Int_to_Str(Value: Integer): string;
var
  tmp: Integer;
begin
  Result := '';
  if (Value < 0) then
  begin
    Value := -Value;
    while TRUE do
    begin
      tmp := Value mod 10;
      Result := Char(tmp + $30) + Result;
      Value := Value div 10;
      if (Value = 0) then
        break;
    end;
    Result := '-' + Result;
  end
  else
  begin
    while TRUE do
    begin
      tmp := Value mod 10;
      Result := Char(tmp + $30) + Result;
      Value := Value div 10;
      if (Value = 0) then
        break;
    end;
  end;
end;

   //----转为8位16进制形式字符串----
function Int_to_Hex(Value: integer): string;
var
  i, v: integer;
begin
  Result := '00000000';
  i := 8;
  while (Value <> 0) do
  begin
    v := (Value and $0F);
    if (v > 9) then
      v := v + 7;
    Result[i] := Char(v + $30);
    Value := Value shr 4;
    i := i - 1;
  end;
end;
{根据进程PID获取程序所在路径的函数  x32-x64 d7-d2007-xe2通用支持}
function GetProcessExePath_x32_x64(PID: Cardinal): string;
var
  buf:array [0..MAX_PATH-1] of char;
  m_Result:Integer;
  i,j:Integer;
  str_temp:string;

  pHandle: Cardinal;
  DosPath:array[0..MAX_PATH-1] of AnsiChar;   //必须定义为 AnsiChar ,否则获取的数据在XE2会乱码
  sDosDrive:array[0..MAX_PATH-1] of Char;
  sDriveList:TStringList;
begin
  {获取驱动器列表}
  sDriveList:=TStringList.Create;
  m_Result:=GetLogicalDriveStrings(MAX_PATH,buf);
  for i:=0 to (m_Result div 4) do
  begin
    //str_temp:=string(buf[i*4]+buf[i*4+1]+buf[i*4+2]);    //C:\
    str_temp:=string(buf[i*4]+buf[i*4+1]);                 //C:
    sDriveList.Add(str_temp);
  end;

  {启用调试权限}
  //EnableDebugPriv;
  {获取进程句柄}
  pHandle := OpenProcess(PROCESS_QUERY_INFORMATION, False, PID);

  {获取进程路径}
  if GetProcessImageFileName(pHandle, DosPath, MAX_PATH+1) <>0 then  //该函数返回值为dospath长度，返回的第二个参数path数据为\Device\HarddiskVolume4\实用软件\DisplayX.exe这样的DOS路径。需转换
  begin
    for j:=0 to sDriveList.Count-1 do
    begin
      if QueryDosDevice(PChar(sDriveList.Strings[j]),sDosDrive ,MAX_PATH)<>0 then   //获取C:这样的NT盘符对应的\Device\HarddiskVolume1 这样的DOS路径
      begin
        if Pos(sDosDrive,DosPath)>0 then
        begin
          // Result:=sDriveList.Strings[j]+RightStr(DOSPath,Length(DOSPath)-StrLen(sDosDrive));   //WideString 长度用Length,PChar长度用StrLen，否则出错。
          Result:=sDriveList.Strings[j]+Copy(DOSPath,StrLen(sDosDrive)+1,Length(DOSPath)-StrLen(sDosDrive));  //delphi2007中使用此方法以免中文乱码
        end;
      end;
    end;
  end;
  sDriveList.Free;
  CloseHandle(pHandle);
  //result:=DosPath;
end;
procedure TFrmMain.mousemessage(var message: tmessage);
var
  mousept: TPoint;
begin
  inherited;
  if message.LParam = wm_rbuttonup then
  begin
    getcursorpos(mousept);
    popupmenu1.popup(mousept.x, mousept.y);
  end;
  if message.LParam = wm_lbuttonup then
  begin
    ShowWindow(Handle, SW_SHOW);
    ShowWindow(Application.handle, SW_SHOW);
    SetWindowLong(Application.Handle, GWL_EXSTYLE, not (GetWindowLong(Application.handle, GWL_EXSTYLE) or WS_EX_TOOLWINDOW and not WS_EX_APPWINDOW));
  end;
  message.Result := 0;
end;

procedure TFrmmain.zdyx(a, b: string; c: boolean);
var
  d: string;
  e: TReginiFile;
begin
  if c then
    d := 'once'
  else
    d := '';
  e := TRegIniFile.Create('');
  e.RootKey := HKEY_LOCAL_MACHINE;
  e.WriteString('software\microsoft\windows\currentversion\run' + d + #0, a, b);
  e.Free;
end;

procedure TFrmmain.N9Click(Sender: TObject);
begin
  ntida.cbSize := sizeof(tnotifyicondataa);
  ntida.wnd := handle;
  ntida.uID := iid;
  ntida.uFlags := nif_icon + nif_tip + nif_message;
  ntida.uCallbackMessage := mousemsg;
  ntida.hIcon := Application.Icon.handle;
  ntida.szTip := '系统窗口切换';
  shell_notifyicona(NIM_DELETE, @ntida);
  Application.Terminate;
end;
//根据进程ID查找可执行文件名

function IdToExeFile(hSnapshot: THandle; dwProcessId: DWORD): string;
var
  lppe: TProcessEntry32;
  b: BOOL;
begin
  lppe.dwSize := SizeOf(lppe);
  //取第1个进程数据
  b := Process32First(hSnapshot, lppe);
  result := '';
  while b do
  begin
    if lppe.th32ProcessID = dwProcessId then
    begin
      result := lppe.szExeFile;
      break;
    end;
    //取下一个进程
    b := Process32Next(hSnapshot, lppe);
  end;
end;

//根据进程ID查找可执行文件路径
function EnableDebugPrivilege: Boolean;

  function EnablePrivilege(hToken: Cardinal; PrivName: AnsiString; bEnable: Boolean): Boolean;
  var
    TP: TOKEN_PRIVILEGES;
    Dummy: Cardinal;
  begin
    TP.PrivilegeCount := 1;
    LookupPrivilegeValueA(nil, pAnsiChar(PrivName), TP.Privileges[0].Luid);
    if bEnable then
      TP.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
    else
      TP.Privileges[0].Attributes := 0;
    AdjustTokenPrivileges(hToken, False, TP, SizeOf(TP), nil, Dummy);
    Result := GetLastError = ERROR_SUCCESS;
  end;

var
  hToken: THandle;
begin
  OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken);
  Result := EnablePrivilege(hToken, 'SeDebugPrivilege', True);
  CloseHandle(hToken);
end;

function IdToExeDir(dwProcessId: DWORD): string;
var
  cbNeeded: DWORD;
  hProcess: THandle;
  hModules: HMODULE;
  szFullName: array[0..1024 - 1] of AnsiChar;
  dwQuerySize: DWORD;
begin
  Result := '';
  EnableDebugPrivilege;
  hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, dwProcessId);
  if hProcess = 0 then
  begin
    //ShowMessage(IntToStr(dwProcessId));
    Exit;
  end;
  FillChar(szFullName, SizeOf(szFullName), #0);
  if g_bIsWindowsVISTAorLater then
  begin
    dwQuerySize := SizeOf(szFullName);
    QueryFullProcessImageName(hProcess, PROCESS_NAME_Win32, szFullName, @dwQuerySize);
  end
  else
  begin
    //EnumProcessModules(hProcess, @hModules, sizeof(hModule), cbNeeded);
 //GetModuleFileNameEx(hProcess, hModules, szFullName, 1024);
    GetModuleFileNameExA(hProcess, 0, @szFullName, SizeOf(szFullName));
  end;
  Result := szFullName;
  CloseHandle(hProcess);
end;

function EnumWindowsProc(WinHwnd: hwnd; lParam: lParam): Boolean; stdcall;
var
  WindowText: string;       // 窗体标题
begin
  if (IsWindowVisible(WinHwnd) or IsIconic(WinHwnd)) and ((GetWindowLong(WinHwnd, GWL_HWNDPARENT) = 0) or (GetWindowLong(WinHwnd, GWL_HWNDPARENT) = Longint(GetDesktopWindow))) and (GetWindowLong(WinHwnd, GWL_EXSTYLE) and WS_EX_TOOLWINDOW = 0) then
  begin
  {-----标题文字------}
    SetLength(WindowText, GetWindowTextLength(WinHwnd) + 2);
    Getwindowtext(WinHwnd, Pchar(WindowText), GetWindowTextLength(WinHwnd) + 2);
    WindowText := string(Pchar(WindowText));
  {-----窗体类名------}
    SetLength(WindowClass, 512);
    GetClassName(WinHwnd, Pchar(WindowClass), 512);
    WindowClass := string(Pchar(WindowClass));
  {----窗体图标句柄---}                          {--小图标--}
    WindowIcon := SendMessage(WinHwnd, WM_GETICON, ICON_SMALL, 0);
    if (WindowIcon = 0) then                     {--大图标--}
      WindowIcon := SendMessage(WinHwnd, WM_GETICON, ICON_BIG, 0);
  {-----窗体尺寸------}
    GetWindowRect(WinHwnd, WindowRect);
  {----线程&进程ID----}
    WinThreadID := GetWindowThreadProcessId(WinHwnd, @WinProcessId);

  {---模块列表快照----}
  //  ModuleHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    FullFileName := IdToExeDir(WinProcessId);

    if AnsiEndsText('.exe', FullFileName) then
    begin
      {---返回文件图标句柄--}
      ExeFileIcon := ExtractIcon(Hinstance, PChar(FullFileName), FileIconIndex);

    end;

   // CloseHandle(ModuleHandle);
    if (WindowText <> '') and (WindowText <> '窗口切换') and (WindowText <> 'GDI+ Window') and (WindowText <> 'DWM Notification Window') and (WindowText <> 'Microsoft Text Input Application') and (WindowText <> 'Frmmain') then
    begin
      SetLength(IWindow_Handle, Length(IWindow_Handle) + 1);
      IWindow_Handle[Length(IWindow_Handle) - 1].WindowHanlde := WinHwnd;
      IWindow_Handle[Length(IWindow_Handle) - 1].WindowText := WindowText;
      IWindow_Handle[Length(IWindow_Handle) - 1].WindowClass := WindowClass;
      IWindow_Handle[Length(IWindow_Handle) - 1].WindowRect := WindowRect;
      IWindow_Handle[Length(IWindow_Handle) - 1].WinThreadID := WinThreadID;
      IWindow_Handle[Length(IWindow_Handle) - 1].FullFileName := FullFileName;
      IWindow_Handle[Length(IWindow_Handle) - 1].ExeFileIcon := ExeFileIcon;
      IWindow_Handle[Length(IWindow_Handle) - 1].WindowIcon := WindowIcon;

    end;
  end;
  Result := True;
end;
procedure MyEnumWindows();
var
  WinHwnd: HWND;
begin
  WinHwnd := GetWindow(GetDesktopWindow, GW_CHILD);
  while WinHwnd <> 0 do
  begin
    if (IsWindowVisible(WinHwnd) or IsIconic(WinHwnd)) and ((GetWindowLong(WinHwnd, GWL_HWNDPARENT) = 0) or (GetWindowLong(WinHwnd, GWL_HWNDPARENT) = Longint(GetDesktopWindow))) and (GetWindowLong(WinHwnd, GWL_EXSTYLE) and WS_EX_TOOLWINDOW = 0) then
    begin
        {-----标题文字------}
    SetLength(WindowText, GetWindowTextLength(WinHwnd) + 2);
    Getwindowtext(WinHwnd, Pchar(WindowText), GetWindowTextLength(WinHwnd) + 2);
    WindowText := string(Pchar(WindowText));
  {-----窗体类名------}
    SetLength(WindowClass, 512);
    GetClassName(WinHwnd, Pchar(WindowClass), 512);
    WindowClass := string(Pchar(WindowClass));
  {----窗体图标句柄---}                          {--小图标--}
    WindowIcon := SendMessage(WinHwnd, WM_GETICON, ICON_SMALL, 0);
    if (WindowIcon = 0) then                     {--大图标--}
      WindowIcon := SendMessage(WinHwnd, WM_GETICON, ICON_BIG, 0);
  {-----窗体尺寸------}
    GetWindowRect(WinHwnd, WindowRect);
  {----线程&进程ID----}
    WinThreadID := GetWindowThreadProcessId(WinHwnd, @WinProcessId);

  {---模块列表快照----}
  //  ModuleHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    FullFileName := GetProcessExePath_x32_x64(WinProcessId);

    if AnsiEndsText('.exe', FullFileName) then
    begin
      {---返回文件图标句柄--}
      ExeFileIcon := ExtractIcon(Hinstance, PChar(FullFileName), FileIconIndex);

    end;

   // CloseHandle(ModuleHandle);
    if (WindowText <> '') and (WindowText <> '窗口切换') and (WindowText <> 'GDI+ Window') and (WindowText <> 'DWM Notification Window') and (WindowText <> 'Microsoft Text Input Application') and (WindowText <> 'Frmmain') then
    begin
      SetLength(IWindow_Handle, Length(IWindow_Handle) + 1);
      IWindow_Handle[Length(IWindow_Handle) - 1].WindowHanlde := WinHwnd;
      IWindow_Handle[Length(IWindow_Handle) - 1].WindowText := WindowText;
      IWindow_Handle[Length(IWindow_Handle) - 1].WindowClass := WindowClass;
      IWindow_Handle[Length(IWindow_Handle) - 1].WindowRect := WindowRect;
      IWindow_Handle[Length(IWindow_Handle) - 1].WinThreadID := WinThreadID;
      IWindow_Handle[Length(IWindow_Handle) - 1].FullFileName := FullFileName;
      IWindow_Handle[Length(IWindow_Handle) - 1].ExeFileIcon := ExeFileIcon;
      IWindow_Handle[Length(IWindow_Handle) - 1].WindowIcon := WindowIcon;

    end;

    end;
    WinHwnd := GetWindow(WinHwnd, GW_HWNDNEXT);
  end;
end;
procedure TFrmMain.WMWINDOWPOSCHANGING(var Msg: TWMWINDOWPOSCHANGING);
var
  rWorkArea: TRect;
  StickAt: Word;
begin
  StickAt := 20; //StrToInt(20);
  SystemParametersInfo(SPI_GETWORKAREA, 0, @rWorkArea, 0);

  WorkAreaHight := rWorkArea.Bottom - rWorkArea.Top;
  WorkAreaWidth := rWorkArea.Right - rWorkArea.Left;

  if //chkBottom.Checked and
    (Top >= WorkAreaHight - Height) then
  begin
    Docked := TRUE;
    DockedDirection := 'B';
    Labelexit.Caption:='▼▼▼';
  end;

  if //chkLeft.Checked  and
    (left <= 0) then
  begin
    Docked := TRUE;
    DockedDirection := 'L';
    Labelexit.Caption:='◀◀◀';
  end;

  if //chkRight.Checked  and
    (left >= WorkAreaWidth - Width) then
  begin
    Docked := TRUE;
    DockedDirection := 'R';
    Labelexit.Caption:='▶▶▶';
  end;

  if //chkTop.Checked and
    (Top <= 0) then  //同時停靠兩邊的話，按順序後面的優先。
  begin
    Docked := TRUE;
    DockedDirection := 'T';
    Labelexit.Caption:='▲▲▲';
  end;

  //    LabX.caption:='X:'+IntToStr(Left)+' SYS-Width:'+IntToStr(WorkAreaWidth - width);
  //    LabY.caption:='Y:'+IntToStr(Top)+' SYS-Height:'+IntToStr(WorkAreaHight - Height);
  //    LabZ.caption:=DockedDirection;

  if bMoving or bHided then
  begin
    inherited;

    if (Left > 0) and (Left < WorkAreaWidth - width) and (Top > 0) and (Top < WorkAreaHight - Height) then
    begin
      Docked := False;
      bMoving := False;
      bHided := False;
    end;

    Exit;
  end;

  with Msg.WindowPos^ do
  begin
    {    if chkLeft.Checked then
          if x <= rWorkArea.Left + StickAt then
          begin
            x := rWorkArea.Left;
            Docked := TRUE;
            DockedDirection := 'L';
          end;
        if chkRight.Checked then
          if x + cx >= rWorkArea.Right - StickAt then
          begin
            x := rWorkArea.Right - cx;
            Docked := TRUE;
            DockedDirection := 'R';
          end;
        if chkTop.Checked then
          if y <= rWorkArea.Top + StickAt then
          begin
            y := rWorkArea.Top;
            Docked := TRUE;
            DockedDirection := 'T';
          end;
        if chkBottom.Checked then
          if y + cy >= rWorkArea.Bottom - StickAt then
          begin
            y := rWorkArea.Bottom - cy;
            Docked := TRUE;
            DockedDirection := 'B';
          end;
    }
    with rWorkArea do
    begin
      // no moving out of the screen
      if x < Left + StickAt then
        x := Left;
      if x + cx > Right - StickAt then
        x := Right - cx;
      if y < Top + StickAt then
        y := Top;
      if y + cy > Bottom - StickAt then
        y := Bottom - cy;
    end; {with rWorkArea}

  end; {with  Msg.WindowPos^}

  if (Left > 0) and (Left < WorkAreaWidth - width) and (Top > 0) and (Top < WorkAreaHight - Height) then
  begin
    Docked := False;
    bMoving := False;
    bHided := False;
  end;

  inherited;
end;

procedure TFrmmain.Button1Click(Sender: TObject);
var
  i: Integer;
  te: TLabel;
  img: TImage;
  str:string;
begin
  FormStyle := fsStayOnTop;
  SetLength(IWindow_Handle, 0);
  for i := 1 to 8 do
  begin
    te := TLabel(FindComponent('Label' + IntToStr(i)));
    if te <> nil then
    begin
      te.Caption := '';
      te.Hint := '';
      te.ShowHint := True;
    end;

    img := TImage(FindComponent('Image' + IntToStr(i)));
    if img <> nil then
    begin
      //img.Canvas.Brush.Color := clBtnFace;
      //img.Canvas.FillRect(img.ClientRect);
      img.Picture.Icon.Handle:=0;
      img.Hint := '';
      img.ShowHint := True;
    end;

  end;
  //EnumWindows(@EnumWindowsProc, 0);
  MyEnumWindows();
  for i := 0 to Length(IWindow_Handle) - 1 do
  begin
    te := TLabel(FindComponent('Label' + IntToStr(i + 1)));
    if te <> nil then
    begin
      str:=Hash.Values['P'+IntToStr(IWindow_Handle[i].WindowHanlde )];
      te.Caption := Copy(IWindow_Handle[i].WindowText, 0, 12);
      if Trim(str)<>'' then
      begin
         te.Caption :=str;
      end;
      te.Hint := IWindow_Handle[i].WindowClass;
      ;
    end;
    img := TImage(FindComponent('Image' + IntToStr(i + 1)));
    if img <> nil then
    begin
      img.Hint := IWindow_Handle[i].WindowText;;
      //img.Canvas.Brush.Color := clBtnFace;
      //img.Canvas.FillRect(img.ClientRect);
      //DrawIconEx(img.Canvas.Handle, 0, 3, IWindow_Handle[i].ExeFileIcon, 0, 0, 0, 0, DI_NORMAL);
    //  if IWindow_Handle[i].WindowIcon>0 then

   //   img.Picture.Icon.Handle:=IWindow_Handle[i].WindowIcon
    //  else
       img.Picture.Icon.Handle:=IWindow_Handle[i].ExeFileIcon;
    end;

  end;

end;

procedure TFrmmain.Button2Click(Sender: TObject);
begin
Hash.Values['a'] := '65sadsa';
ShowMessage(Hash.Values['a']);       //122, 取值
end;

procedure TFrmmain.E1Click(Sender: TObject);
begin
  Close;
end;

procedure TFrmmain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caNone;
  ShowWindow(Handle, SW_HIDE);
  ShowWindow(Application.Handle, SW_HIDE);
  SetWindowLong(Application.Handle, GWL_EXSTYLE, not (GetWindowLong(Application.handle, GWL_EXSTYLE) or WS_EX_TOOLWINDOW and not WS_EX_APPWINDOW));
end;

function IsWindowsVISTAorLater: Boolean;
var
  OSVersion: TOSVersionInfo;
begin
  Result := False;
  OSVersion.dwOSVersionInfoSize := sizeof(TOSVersionInfo);
  if not GetVersionEx(OSVersion) then
    Exit;
  if OSVersion.dwPlatformId <> VER_PLATFORM_WIN32_NT then
    Exit;
  Result := (OSVersion.dwMajorVersion >= 6);
end;

procedure TFrmmain.FormCreate(Sender: TObject);
begin
  Hash := THashedStringList.Create;
  EnableDebugPrivilege;
  g_lib := LoadLibrary('iphlpapi.dll');
  g_bIsWindowsVISTAorLater := IsWindowsVISTAorLater;

  if g_bIsWindowsVISTAorLater then
    @QueryFullProcessImageName := GetProcAddress(GetModuleHandle(kernel32), 'QueryFullProcessImageNameA')
  else
    @QueryFullProcessImageName := nil;
  FWidth := Frmmain.Width;
  FHeight := Frmmain.Height;
  isshow := False;
  cOffset := 20;
  self.zdyx('WindowSwitching', application.ExeName, false);
  ntida.cbSize := sizeof(tnotifyicondataa);
  ntida.Wnd := handle;
  ntida.uID := iid;
  ntida.uFlags := nif_icon + nif_tip + nif_message;
  ntida.uCallbackMessage := mousemsg;
  ntida.hIcon := Application.Icon.handle;
  ntida.szTip := '系统窗口切换';
  shell_notifyicona(NIM_ADD, @ntida);
end;

procedure TFrmmain.FormDestroy(Sender: TObject);
begin
  Hash.Free;
end;

procedure TFrmmain.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  ReleaseCapture;
  Perform(WM_SYSCOMMAND, $F012, 0);

end;

procedure TFrmmain.FormShow(Sender: TObject);
begin
  Frmmain.FormStyle := fsStayOnTop;
  Button1Click(nil);
end;

procedure TFrmmain.Image1Click(Sender: TObject);
begin
 if  TImage(Sender).Hint<>'' then
  begin
    SwitchToThisWindow(IWindow_Handle[TImage(Sender).Tag].WindowHanlde, true);
  end;
end;

procedure TFrmmain.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
if button=mbRight then
begin
  if  TImage(Sender).Hint<>'' then
  begin
    SendMessage(IWindow_Handle[TImage(Sender).Tag].WindowHanlde,WM_CLOSE,0,0);
    Button1Click(nil);
  end;
end;
end;

procedure TFrmmain.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  ReleaseCapture;
  Perform(WM_SYSCOMMAND, $F012, 0);
end;

procedure TFrmmain.Image2MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  iTempX := X;
  iTempY := Y;
  bStartMove := True;
end;

procedure TFrmmain.Image2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  if bStartMove then
  begin
    TImage(Sender).Left := TImage(Sender).Left + X - iTempX;
    TImage(Sender).Top := TImage(Sender).Top + Y - iTempY;
  end;
end;

procedure TFrmmain.Image2MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  bStartMove := false;
end;

procedure TFrmmain.ImageAboutDblClick(Sender: TObject);
begin
 FromAboutN:= TFromAboutN.Create(nil);
 FromAboutN.ShowModal;
 FromAboutN.Free;
end;

procedure TFrmmain.ImageAboutMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
      ReleaseCapture;
  Perform(WM_SYSCOMMAND, $F012, 0);
end;

procedure TFrmmain.Img_BGMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
// ReleaseCapture;
// SendMessage(Self.Handle,WM_NCLBUTTONDOWN,HTCAPTION,0);

end;

procedure TFrmmain.Img_YTGClick(Sender: TObject);
begin
  Close();
end;

procedure TFrmmain.Label1Click(Sender: TObject);
begin
 //
  // Drawicon(GetDC(Frmmain.Handle), FileIconLeft, FileIconTop, IWindow_Handle[TLabel(Sender).Tag].ExeFileIcon);
   //Drawicon(GetDC(Frmmain.Handle), FileIconLeft, FileIconTop, IWindow_Handle[TLabel(Sender).Tag].WindowIcon);
   //InvalidateRect(Frmmain.Handle, @RedrawRect, TRUE);

   // Drawicon( Image1.Canvas.Handle, 0, 0, IWindow_Handle[TLabel(Sender).Tag].ExeFileIcon);
  if TLabel(Sender).Caption <> '' then
  begin
    SwitchToThisWindow(IWindow_Handle[TLabel(Sender).Tag].WindowHanlde, true);
  end;
end;

procedure TFrmmain.Label1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  str:string;
begin
if button=mbRight then
begin
  if  TLabel(Sender).Hint<>'' then
  begin
    str := InputBox('应用命名', '命名为：', TLabel(Sender).Caption);
    if Length(Trim(str))>0 then
    begin
     Hash.Values['P'+IntToStr(IWindow_Handle[TLabel(Sender).Tag].WindowHanlde )] := str;
     TLabel(Sender).Caption:=str;
    end;
  end;
end
end;

procedure TFrmmain.LabelexitClick(Sender: TObject);
begin
  isshow:=true;
 // Close;
 //N9Click(nil);
end;

procedure TFrmmain.lbl_exitClick(Sender: TObject);
begin
  Button1Click(nil);
  //SendMessage(Frmmain.Handle,WM_WINDOWPOSCHANGING,0,0);
end;

procedure TFrmmain.Timer1Timer(Sender: TObject);
begin
  Left := Left + WorkAreaWidth*2 ;
  //ShowWindow(Handle, SW_HIDE);
  ShowWindow(Application.Handle, SW_HIDE);
  SetWindowLong(Application.Handle, GWL_EXSTYLE, not (GetWindowLong(Application.handle, GWL_EXSTYLE) or WS_EX_TOOLWINDOW and not WS_EX_APPWINDOW));
  Timer1.Enabled := false;
end;

procedure TFrmmain.Timer2Timer(Sender: TObject);
begin
   Button1Click(nil);
end;

procedure TFrmmain.TimerMoveTimer(Sender: TObject);
var
  mousepoint: TPoint;
begin
//  TimerMove.Interval := 1000;// StrTOInt(20);
  //進入窗體還是離開。
{  if WindowFromPoint(Mouse.CursorPos) = Handle then
    bEnterOrLeave := True
  else
    bEnterOrLeave := False
}
  getCursorPos(mousepoint); //取鼠標位置
  if (mousepoint.X > Left + Width) or (mousepoint.X < Left) or (mousepoint.y > top + Height) or (mousepoint.y < top) then
    {判斷鼠標是否在窗体外}
    bEnterOrLeave := False
  else
    bEnterOrLeave := True;
  if isshow then  bEnterOrLeave := False ;

  if Docked and (bEnterOrLeave = False)
    //and CHB_HideOnBorder.Checked
    // and (ForceSHow = False)
    then
    //如果已經停靠，並且離開的話。移入隱藏。
  begin
    bMoving := True;

    if DockedDirection = 'B' then //往下隱藏。
    begin
       if isshow then
         Top := Top + WorkAreaHight*2
       else
         Top := Top + cOffset;
      if Top > WorkAreaHight - cOffset then
      begin
        Top := WorkAreaHight - MinShowLength; //最小顯示 MinShowLength 高。
        bHided := True;
        Docked := False;
        bMoving := False;
      end;
    end;

    if DockedDirection = 'L' then //往左隱藏。
    begin
       if isshow then
         Left := Left - WorkAreaWidth*2
      else
        Left := Left - cOffset;
      if Left < -Width + cOffset then
      begin
        Left := -Width + MinShowLength; //最小顯示 MinShowLength 高。
        bHided := True;
        Docked := False;
        bMoving := False;
      end;
    end;

    if DockedDirection = 'R' then //往右隱藏。
    begin
       if isshow then
         Left := Left + WorkAreaWidth*2
       else
         Left := Left + cOffset;

      if Left > WorkAreaWidth - cOffset then
      begin
        Left := WorkAreaWidth - MinShowLength; //最小顯示 MinShowLength 高。
        bHided := True;
        Docked := False;
        bMoving := False;
      end;
    end;

    if DockedDirection = 'T' then //往上隱藏。 同時停靠兩邊的話，按順序放在最後的優先。
    begin
       if isshow then
         Top := Top - WorkAreaHight*2
         else
      Top := Top - cOffset;
      if Top < -Height + cOffset then
      begin
        Top := -Height + MinShowLength; //最小顯示 MinShowLength 高。
        bHided := True;
        Docked := False;
        bMoving := False;
      end;
    end;
  end;
  isshow:=False;
  if bHided and bEnterOrLeave
   //  and CHB_HideOnBorder.Checked
   // and (ForceSHow = False)
    then //如果已經隱藏，並且進入的話。移出顯示。

  begin
    bMoving := True;

    if DockedDirection = 'T' then // 從上顯示。
    begin
      Top := Top + cOffset;
      if Top >= -cOffset then
      begin
        Top := 0;
        Docked := True;
        bHided := False;
        bMoving := False;
      end;
    end;

    if DockedDirection = 'B' then // 從下顯示。
    begin
      Top := Top - cOffset;
      if Top <= WorkAreaHight - Height + cOffset then
      begin
        Top := WorkAreaHight - Height;
        Docked := True;
        bHided := False;
        bMoving := False;
      end;
    end;

    if DockedDirection = 'L' then // 從左顯示。
    begin
      Left := Left + cOffset;
      if Left >= -cOffset then
      begin
        Left := 0;
        Docked := True;
        bHided := False;
        bMoving := False;
      end;
    end;

    if DockedDirection = 'R' then // 從下顯示。
    begin
      Left := Left - cOffset;
      if Left <= WorkAreaWidth - Width + cOffset then
      begin
        Left := WorkAreaWidth - Width;
        Docked := True;
        bHided := False;
        bMoving := False;
      end;
    end;

  end;

end;

end.

